﻿using System;
using System.IO;
using GeoAPI.Geometries;
using NetTopologySuite.Geometries;

namespace NetTopologySuite.GeometriesGraph
{
	public class DirectedEdge : EdgeEnd
	{
		public static int DepthFactor(Location currLocation, Location nextLocation)
		{
			if (currLocation == Location.Exterior && nextLocation == Location.Interior)
			{
				return 1;
			}
			if (currLocation == Location.Interior && nextLocation == Location.Exterior)
			{
				return -1;
			}
			return 0;
		}

		public DirectedEdge(Edge edge, bool isForward) : base(edge)
		{
			this._isForward = isForward;
			if (isForward)
			{
				base.Init(edge.GetCoordinate(0), edge.GetCoordinate(1));
			}
			else
			{
				int num = edge.NumPoints - 1;
				base.Init(edge.GetCoordinate(num), edge.GetCoordinate(num - 1));
			}
			this.ComputeDirectedLabel();
		}

		public bool InResult
		{
			get
			{
				return this._isInResult;
			}
			set
			{
				this._isInResult = value;
			}
		}

		public bool IsInResult
		{
			get
			{
				return this._isInResult;
			}
		}

		public bool Visited
		{
			get
			{
				return this._isVisited;
			}
			set
			{
				this._isVisited = value;
			}
		}

		public bool IsVisited
		{
			get
			{
				return this._isVisited;
			}
		}

		public EdgeRing EdgeRing { get; set; }

		public EdgeRing MinEdgeRing { get; set; }

		public int GetDepth(Positions position)
		{
			return this._depth[(int)position];
		}

		public void SetDepth(Positions position, int depthVal)
		{
			if (this._depth[(int)position] != -999 && this._depth[(int)position] != depthVal)
			{
				throw new TopologyException("assigned depths do not match", base.Coordinate);
			}
			this._depth[(int)position] = depthVal;
		}

		public int DepthDelta
		{
			get
			{
				int num = base.Edge.DepthDelta;
				if (!this.IsForward)
				{
					num = -num;
				}
				return num;
			}
		}

		public bool VisitedEdge
		{
			get
			{
				return this.Visited && this._sym.Visited;
			}
			set
			{
				this.Visited = value;
				this._sym.Visited = value;
			}
		}

		public bool IsForward
		{
			get
			{
				return this._isForward;
			}
			protected set
			{
				this._isForward = value;
			}
		}

		public DirectedEdge Sym
		{
			get
			{
				return this._sym;
			}
			set
			{
				this._sym = value;
			}
		}

		public DirectedEdge Next { get; set; }

		public DirectedEdge NextMin { get; set; }

		public bool IsLineEdge
		{
			get
			{
				bool flag = base.Label.IsLine(0) || base.Label.IsLine(1);
				bool flag2 = !base.Label.IsArea(0) || base.Label.AllPositionsEqual(0, Location.Exterior);
				bool flag3 = !base.Label.IsArea(1) || base.Label.AllPositionsEqual(1, Location.Exterior);
				return flag && flag2 && flag3;
			}
		}

		public bool IsInteriorAreaEdge
		{
			get
			{
				bool result = true;
				for (int i = 0; i < 2; i++)
				{
					if (!base.Label.IsArea(i) || base.Label.GetLocation(i, Positions.Left) != Location.Interior || base.Label.GetLocation(i, Positions.Right) != Location.Interior)
					{
						result = false;
					}
				}
				return result;
			}
		}

		private void ComputeDirectedLabel()
		{
			base.Label = new Label(base.Edge.Label);
			if (!this._isForward)
			{
				base.Label.Flip();
			}
		}

		public void SetEdgeDepths(Positions position, int depth)
		{
			int num = base.Edge.DepthDelta;
			if (!this._isForward)
			{
				num = -num;
			}
			int num2 = 1;
			if (position == Positions.Left)
			{
				num2 = -1;
			}
			Positions position2 = Position.Opposite(position);
			int num3 = num * num2;
			int depthVal = depth + num3;
			this.SetDepth(position, depth);
			this.SetDepth(position2, depthVal);
		}

		[Obsolete("Use SetEdgeDepths instead")]
		public void OLDSetEdgeDepths(Positions position, int depth)
		{
			int depthDelta = base.Edge.DepthDelta;
			Location location = base.Label.GetLocation(0, position);
			Positions positions = Position.Opposite(position);
			Location location2 = base.Label.GetLocation(0, positions);
			int num = System.Math.Abs(depthDelta) * DirectedEdge.DepthFactor(location, location2);
			int depthVal = depth + num;
			this.SetDepth(position, depth);
			this.SetDepth(positions, depthVal);
		}

		public override void Write(StreamWriter outstream)
		{
			base.Write(outstream);
			outstream.Write(string.Concat(new object[]
			{
				" ",
				this._depth[1],
				"/",
				this._depth[2]
			}));
			outstream.Write(" (" + this.DepthDelta + ")");
			if (this._isInResult)
			{
				outstream.Write(" inResult");
			}
		}

		public void WriteEdge(StreamWriter outstream)
		{
			this.Write(outstream);
			outstream.Write(" ");
			if (this._isForward)
			{
				base.Edge.Write(outstream);
				return;
			}
			base.Edge.WriteReverse(outstream);
		}

		private bool _isForward;

		private bool _isInResult;

		private bool _isVisited;

		private DirectedEdge _sym;

		private readonly int[] _depth = new int[]
		{
			0,
			-999,
			-999
		};
	}
}
